/*!
   \file

   © 2011 Mark W. Gabby II

   This file is part of Rock Hunter.

   Rock Hunter is free software: you can redistribute it and/or modify it under the terms of the
   GNU General Public License as published by the Free Software Foundation, either version 3 of the
   License, or (at your option) any later version.

   Rock Hunter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
   even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License along with Rock Hunter.
   If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include "Systems/Constants/PlatformTypes.hpp"

#define WIN32_LEAN_AND_MEAN
#ifndef WINVER
#define WINVER 0x501 // Windows XP
#endif
#include <windows.h>
#include <mmsystem.h>

class WindowsWindow
{
public:
   WindowsWindow();
   ~WindowsWindow() {}

   bool Initialize( const bool Border, tPixelFormatIndex PixelFormatIndex,
                    const uint16_t WidthPixels, const uint16_t HeightPixels,
                    const int16_t PixelPositionX, const int16_t PixelPositionY,
                    const float CustomFOV, const float CustomAspectRatio,
                    const char * const Name, const char * const Caption );

   bool CaptureController( const tControllerIndex Index );
   bool ReleaseController();
   bool ControllerCaptured();
   tControllerIndex GetControllerIndex();

   /*!
      \brief
         Activates the window's OpenGL context for rendering.
      \note
         By default, a window's context is inactive. This MUST be called on at least one window
         before any rendering can happen.
   */
   void ActivateContext();
   void DeactivateContext();
   /// \brief Swaps the front and back buffer, so as to display stuff drawn on the back buffer.
   void SwapBuffers();
   /// \brief Returns the windows window handle for this window.
   HWND GetHandle();
   tWindowID GetID();

   void UpdateMouseVisibility( const int16_t PosX, const int16_t posY );
   bool AllMouseButtonsReleased();
   bool MouseCaptured();
   bool ShouldReleaseMouse();
   bool ShouldHideMouse( const int16_t PosX, const int16_t posY );

   virtual void MaybeReleaseMouse( int8_t ButtonIndex );
   virtual void MaybeCaptureMouse( int8_t ButtonIndex );

   void HideMouse();
   void ShowMouse();
   void CaptureMouse();
   void ReleaseMouse();

   void SendInputKeyboardKeyMessage( UINT Msg, WPARAM WParam, LPARAM LParam );
   void SendInputKeyboardKeyValueMessage( UINT Msg, WPARAM WParam, LPARAM LParam );
   void SendInputMouseButtonMessage( UINT Msg, WPARAM WParam, LPARAM LParam );
   void SendInputMouseMoveMessage( UINT Msg, WPARAM WParam, LPARAM LParam );
   void SendInputMouseWheelMessage( UINT Msg, WPARAM WParam, LPARAM LParam );

   void SendInputControllerUpdates( JOYINFOEX & ControllerStatus );
   void SendInputControllerButtonMessage( const eKeyState State, const uint32_t ButtonFlag );
   void SendInputControllerAxisMessage( const float Amount, const eControllerAxis Which );

private:
   bool MouseInWindow( const int16_t PosX, const int16_t posY );

   HGLRC openGLContextHandle;
   HWND windowHandle;

   tControllerIndex capturedControllerIndex;
   JOYINFOEX previousControllerStatus;
   JOYCAPS controllerCaps;

   bool joySetCaptureCalled;

   uint32_t borderWidthX;
   uint32_t borderWidthY;
   uint32_t captionWidth;

   struct
   {
      bool mouseButtonCaptured[kMaxMouseButtons];
      bool mouseCaptured;
      bool mouseHidden;
   } input;

   tWindowID id;
};
